/**
 * 
 */
package gui.views;

import gui.TypeListWidget;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashSet;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import application.Application;
import application.GlobalContext;

/**
 * @author Joshua Lockerman
 *
 */
public class CreateTypeView extends JFrame {
    
    private class AddToSuperTypesAction extends AbstractAction {
        
        @Override
        public void actionPerformed(ActionEvent e)
        {
            addSelectedTypeToSupertypes();
        }
    }
    
    private final GlobalContext context;
    
    private JTextField typeName;
    private JTextArea typeDescription;
    
    private HashSet<metagrammar.Type> superTypesSet;
    private DefaultListModel<metagrammar.Type> superTypes;
    private JList<metagrammar.Type> superTypesList;
    
    private TypeListWidget typeListWidget;
    
    public CreateTypeView()
    {
        super("Create Type");
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        
        context = Application.injector.getInstance(GlobalContext.class);
        
        setLayout(new BorderLayout());
        
        createAddType();
        pack();
    }
    
    private void createAddType()
    {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLayout(new BorderLayout());
        
        
        Component textPanel = createTextPanel();
        add(textPanel, BorderLayout.CENTER);
        
        JPanel listPanel = new JPanel();
        JButton button = new JButton(new AddToSuperTypesAction());
        button.setText("<-");
        listPanel.add(button);
        listPanel.add(createTypeListWidget());
        add(listPanel, BorderLayout.EAST);
        
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new FlowLayout());
        
        JButton okButton = new JButton();
        okButton.setAction(new AbstractAction("Add") {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                createType();
            }
        });
        buttonPanel.add(okButton);
        
        JButton cancelButton = new JButton();
        cancelButton.setAction(new AbstractAction("Cancel") {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                dispose();
            }
        });
        buttonPanel.add(cancelButton);
        add(buttonPanel, BorderLayout.SOUTH);
    }
    
    private Component createTypeListWidget()
    {
        typeListWidget = new TypeListWidget();
        MouseListener doubleClickListener = new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if(e.getClickCount() == 2) {
                    addSelectedTypeToSupertypes();
                }
            }
        };
        typeListWidget.addMouseListenerToList(doubleClickListener);
        return typeListWidget;
    }
    
    private Component createTextPanel()
    {
        JPanel textPanel = new JPanel();
        textPanel.setLayout(new BorderLayout());
        
        typeName = new JTextField(10);
        typeName.setEditable(true);
        typeName.setBorder(BorderFactory.createTitledBorder("Name"));
        textPanel.add(typeName, BorderLayout.NORTH);
        
        typeDescription = new JTextArea(5, 30);
        typeDescription.setEditable(true);
        typeDescription.setLineWrap(false);
        JScrollPane scroll = new JScrollPane(typeDescription,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scroll.setBorder(BorderFactory.createTitledBorder("Description"));
        textPanel.add(scroll, BorderLayout.CENTER);
        
        textPanel.add(createSupertypesList(), BorderLayout.EAST);
        return textPanel;
    }
    
    private Component createSupertypesList()
    {
        superTypesSet = new HashSet<metagrammar.Type>();
        superTypes = new DefaultListModel<metagrammar.Type>();
        superTypesList = new JList<metagrammar.Type>(superTypes);
        superTypesList.setLayoutOrientation(JList.VERTICAL);
        superTypesList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if(e.getClickCount() == 2) {
                    int index = superTypesList.getSelectedIndex();
                    metagrammar.Type type = superTypes.remove(index);
                    superTypesSet.remove(type);
                }
            }
        });
        JScrollPane sp = new JScrollPane(superTypesList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        sp.setBorder(BorderFactory.createTitledBorder("Supertypes"));
        sp.setPreferredSize(new Dimension(80, 50));
        return sp;
    }
    
    private void addSelectedTypeToSupertypes()
    {
        metagrammar.Type potentialSuperType = typeListWidget.getSelectedType();
        addToSuperTypes(potentialSuperType);
    }
    
    /**
     * @param potentialSuperType
     * @return 
     */
    private boolean addToSuperTypes(metagrammar.Type potentialSuperType)
    {
        if( !superTypesSet.contains(potentialSuperType)) {
            superTypes.addElement(potentialSuperType);
            superTypesSet.add(potentialSuperType);
            pack();
            return true;
        }
        return false;
    }
    
    private void createType()
    {
        String name = typeName.getText();
        if(name.isEmpty()) {
            JOptionPane.showMessageDialog(this, "The name of the new type cannot be empty.",
                    "Type creation error.", JOptionPane.ERROR_MESSAGE);
            return;
        }
        String description = typeDescription.getText();
        metagrammar.Type newType;
        if(superTypes.isEmpty()) {
            newType = new metagrammar.Type(name, description);
        }
        else {
            metagrammar.Type[] supertypes = new metagrammar.Type[superTypes.size()];
            superTypesSet.toArray(supertypes);
            newType = new metagrammar.Type(name, description, supertypes);
        }
        context.add(newType);
        JOptionPane.showMessageDialog(this, "Type " + newType + " added.");
        dispose();
    }
}
